#ifndef __DETECT
#define __DETECT
#include "type.h"
#include <string>
#include "denfunc.h"
/// detect particle information by some paramters, can set the detector position, size and energy detection range
class __Detector
{
    public:
        int id;
        /// capture which kind of particles
        int species;
        /// time step of simualtion
        double delta_t;
        /// if detect by energy range
        int if_ek = 0;
        /// energy range
        __Vect2<double> ekrange;
        /// spatial domain of detector box
        __Vect2<double> xymin;
        __Vect2<double> xymax;
        /// face to which surface
        int front;
        /// deltax of cell
        __Vect2<double> dxy;
        /// along x, or y
        int dir = 0;
        vector<__Vect2<int> > cell_pos; 
        __Ptclslist mylist;
        int total;
    public:
        __Detector(){ total = 0;}
        __Detector(const int id, const int species, const __Vect2<double>& ekrange, \
                const __Vect2<double>& xymin, const __Vect2<double>& xymax, const __Vect2<double>& dxy)\
            :id(id), species(species), ekrange(ekrange), xymin(xymin), xymax(xymax), dxy(dxy){
                total = 0;
            }
        /// initialize the simbox
        void init(__Simbox& mybox);
        /// perform a detection
        void detect(__Simbox& mybox);
        ~__Detector(){ 
            mylist.clear();
            mylist.squeeze();
        }
        void destroy(){
            cell_pos.clear();
            mylist.clear();
            mylist.squeeze();
        }
        /// reset the detector
        void reset(){
            mylist.clear();
            mylist.squeeze();
        }
        /// line function of this detector surface
        double myy(const double& x);
        int is_near(const __Vect2<double>& posi);
        void dump(const int& rank, const int& n, string fname);

};

void __Detector::init(__Simbox& mybox)
{
    dir = 1;
    delta_t = mybox.delta_t;
    __Cellgroup& mygroup = mybox.cellgroup;
    for(int i = 0; i < mygroup.member.size(); i ++)
    {
        for(int j = 0; j < mygroup.member[i].size(); j ++)
        {
            __Cellinfo& mycell = mygroup.member[i][j];
            //__Vect2<int> temp(i, j);
            //cout<<"i, j "<<i<<"\t"<<j<<" myy - y "<<myy(mycell.xymin.member[0]) - mycell.xymin.member[1]<<endl;
            if(is_near(mycell.xymin))
            {
                cell_pos.push_back(__Vect2<int>(i, j));
                //cout<<"cell pushed "<<i<<"\t"<<j<<endl;
            }
            /***
            if(mycell.xymin.member[0] > xymin.member[0])
            {
                getchar();
            }
            ***/
        }
    }

    //cout<<cell_pos.size()<<endl;

}

/// return -1, 0, 1 3 types of near, 0: far, -1: near under, 1: near above
int __Detector::is_near(const __Vect2<double>& posi)
{
    //cout<<"testing "<<posi<<endl;
    if(!(posi.member[0] > xymin.member[0] - dxy.member[0] && \
                posi.member[0] < xymax.member[0] + dxy.member[0] && \
                posi.member[1] > xymin.member[1] - dxy.member[1] && \
                posi.member[1] < xymax.member[1] + dxy.member[1]))
    {
        //cout<<" out of range "<<endl;
        return 0;
    }
    //cout<<"xymin "<<xymin<<" xymax "<<xymax<<"\t"<<posi<<endl;
    if(abs(posi.member[1 - dir] - myy(posi.member[dir])) < 2.0 * dxy.member[0])
    {
        //cout<<" accepted "<<endl;
        return 1;
    }
    else
    {
        //cout<<" too far "<<endl;
        //cout<<abs(posi.member[1 - dir] - myy(posi.member[dir]))<<" is the size "<<2.0 * dxy.member[0]<<endl;
        return 0;
    }

}




void __Detector::detect(__Simbox& mybox)
{
    for(int i = 0; i < cell_pos.size(); i ++)
    {
        __Cellinfo& mycell = mybox.cellgroup.member[cell_pos[i].member[0]][cell_pos[i].member[1]];
        //cout<<" inspecting cell "<<mycell.xymin<<endl;
        if(mycell.plist.size() < species)
        {
            //cout<<" detect noexsiting species "<<endl;
            return;
        }
        if(mycell.plist[species].size() == 0)
        {
            //cout<<" current cell empty of species "<<species<<endl;
            continue;
        }
        for(int j = 0; j < mycell.plist[species].size(); j ++)
        {
            __Ptcls& myptcl = mycell.plist[species].member[j];
            if((myy(myptcl.position.member[dir]) - myptcl.position.member[1 - dir]) * \
                    (myy(myptcl.old_pos.member[dir]) - myptcl.old_pos.member[1 - dir]) <= 0)
            {
                if(if_ek)
                {
                    if(myptcl.energy < ekrange.member[1] && myptcl.energy >= ekrange.member[0])
                    {
                        //__Ptcls tempptcls = myptcl;
                        //tempptcls.total_id --;
                        mylist.push(myptcl);
                    }
                }else
                {
                    //__Ptcls tempptcls = myptcl;
                    //tempptcls.total_id --;
                    mylist.push(myptcl);
                }
            }
        }
    }
    for(int i = 0; i < mybox.crossing_bd_ptcls[species].size(); i ++)
    {
        __Ptcls& myptcl = mybox.crossing_bd_ptcls[species][i];
        if((myy(myptcl.position.member[0]) - myptcl.position.member[1]) * \
                (myy(myptcl.old_pos.member[0]) - myptcl.old_pos.member[0]) <= 0)
        {
            cout<<"ptcl passing __Detector "<<myptcl.old_pos<<"\t"<<myptcl.position<<endl;
            __Ptcls tempptcls = myptcl;
            tempptcls.total_id --;
            mylist.push(myptcl);
        }
    }
}
        



double __Detector::myy(const double& x)
{
    return x / 80 + 100.0 * UNITS;
    //return 80 * (x - 10.0 * UNITS);
}



void __Detector::dump(const int& rank, const int& n, string fname)
{
    stringstream tempstream;
    string tempint;
    if(n < 10){
        tempstream<<"0000";
    }
    else if(n < 100){
        tempstream<<"000";
    }else if(n < 1000){
        tempstream<<"00";
    }else if(n < 10000){
        tempstream<<"0";
    }
    tempstream<<n;
    tempstream<<"_rank_";
    tempstream<<rank;
    tempstream<<"_detector_";
    tempstream<<id;
    tempstream>>tempint;
    fname = fname + tempint;
    ofstream out;
    out.open(fname + ".txt");
    for(int i = 0; i < mylist.size(); i ++)
    {
        out<<mylist.member[i]<<endl;
    }
    out.close();
    //mylist.clear();
    //mylist.squeeze();
}







#endif
